﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKArchMethodLibrary.Utils;
using YJKRGeometry;

namespace YJKArchMethodLibrary.StructurePoleSuit
{
	public class WallInfos
	{
		public XYZ Start
		{
			get
			{
				return this.m_Start;
			}
			set
			{
				this.m_Start = value;
			}
		}

		public XYZ End
		{
			get
			{
				return this.m_End;
			}
			set
			{
				this.m_End = value;
			}
		}

		public double Bugle
		{
			get
			{
				return this.m_Bugle;
			}
		}

		public double Thickness
		{
			get
			{
				return this.m_Thickness;
			}
		}

		public ElementId Id
		{
			get
			{
				return this.m_Id;
			}
			set
			{
				this.m_Id = value;
			}
		}

		public ElementId WallId
		{
			get
			{
				return this.m_WallId;
			}
		}

		public WallInfos(WallInfos rhs)
		{
			this.m_Start = rhs.Start;
			this.m_End = rhs.End;
			this.m_Bugle = rhs.Bugle;
			this.m_Thickness = rhs.Thickness;
			this.m_Id = rhs.Id;
			this.m_WallId = rhs.m_WallId;
		}

		public WallInfos(XYZ start, XYZ end, double bugle, double thickness, ElementId id, ElementId wallId)
		{
			this.m_Start = start;
			this.m_End = end;
			this.m_Bugle = bugle;
			this.m_Thickness = thickness;
			this.m_Id = id;
			this.m_WallId = wallId;
		}

		public bool IsArcWall
		{
			get
			{
				return !YJKRGeometry.Geometry.IsEqual(this.m_Bugle, 0.0);
			}
		}

		public XYZ Center
		{
			get
			{
				XYZ result = new XYZ();
				YJKRGeometry.Geometry.GetCenterWithBulge(this.m_Start, this.m_End, this.m_Bugle, ref result);
				return result;
			}
		}

		public Curve GetCurve(Autodesk.Revit.ApplicationServices.Application app)
		{
			Curve result;
			if (this.IsArcWall)
			{
				XYZ normal = XYZ.BasisZ;
				if (YJKRGeometry.Geometry.LessThan(this.m_Bugle, 0.0))
				{
					normal = -XYZ.BasisZ;
				}
				XYZ radianPnt = YJKRGeometry.Geometry.CalculatMidPoint(this.m_Start, this.m_End, this.Center, normal);
				result = app.CreatYJKArc(this.m_Start, this.m_End, radianPnt);
			}
			else
			{
				result = YJKLineEx.YJKGetBound(this.m_Start, this.m_End);
			}
			return result;
		}

		public bool SplitTest(WallInfos other, Autodesk.Revit.ApplicationServices.Application app, ref List<WallInfos> parts)
		{
			Curve curve = other.GetCurve(app);
			Curve curve2 = this.GetCurve(app);
			Line line = curve2 as Line;
			if (null != line)
			{
				SetComparisonResult setComparisonResult = 0;
				IntersectionResultArray intersectionResultArray;
				try
				{
					setComparisonResult = line.Intersect(curve, out intersectionResultArray);
				}
				catch (Exception)
				{
					return false;
				}
				if (setComparisonResult != SetComparisonResult.Overlap)
				{
					return false;
				}
				List<XYZ> list = new List<XYZ>();
				list.Add(this.m_Start);
				list.Add(this.m_End);
				foreach (object obj in intersectionResultArray)
				{
					IntersectionResult intersectionResult = (IntersectionResult)obj;
					list.Add(intersectionResult.XYZPoint);
				}
				return this.SplitLineWallTest(curve2, list, ref parts);
			}
			else
			{
				Arc arc = curve2 as Arc;
				if (!(null != arc))
				{
					return false;
				}
				SetComparisonResult setComparisonResult2 = 0;
				IntersectionResultArray intersectionResultArray2;
				try
				{
					setComparisonResult2 = arc.Intersect(curve, out intersectionResultArray2);
				}
				catch (Exception)
				{
					return false;
				}
				if ((int)setComparisonResult2 != 8)
				{
					return false;
				}
				List<XYZ> list2 = new List<XYZ>();
				list2.Add(this.m_Start);
				list2.Add(this.m_End);
				foreach (object obj2 in intersectionResultArray2)
				{
					IntersectionResult intersectionResult2 = (IntersectionResult)obj2;
					list2.Add(intersectionResult2.XYZPoint);
				}
				return this.SplitArcWallTest(curve2, list2, ref parts);
			}
			bool result;
			return result;
		}

		private bool SplitLineWallTest(Curve curve, List<XYZ> pointArray, ref List<WallInfos> parts)
		{
            List<XYZ> list = YJKArchMethodLibrary.Utils.Common.UniqueAndSortIntersectPoints(curve, pointArray);
			List<WallInfos> list2 = new List<WallInfos>();
			for (int i = 0; i < list.Count - 1; i++)
			{
				XYZ start = list[i];
				XYZ end = list[i + 1];
				ElementId id = new ElementId(this.WallId.IntegerValue * 100 + i);
				WallInfos wallInfos = new WallInfos(start, end, 0.0, this.Thickness, id, this.WallId);
                if (!YJKRGeometry.Geometry.LessThan(wallInfos.Length(), YJKArchMethodLibrary.Utils.Common.MMToFeet(10.0)))
				{
					list2.Add(wallInfos);
				}
			}
			if (list2.Count > 1)
			{
				parts.AddRange(list2);
				return true;
			}
			return false;
		}

		private bool SplitArcWallTest(Curve curve, List<XYZ> pointArray, ref List<WallInfos> parts)
		{
            List<XYZ> list = YJKArchMethodLibrary.Utils.Common.UniqueAndSortIntersectPoints(curve, pointArray);
			List<WallInfos> list2 = new List<WallInfos>();
			for (int i = 0; i < list.Count - 1; i++)
			{
				XYZ xyz = list[i];
				XYZ xyz2 = list[i + 1];
				if (!xyz.IsAlmostEqualTo(xyz2, 0.0001))
				{
					ElementId id = new ElementId(this.WallId.IntegerValue * 100 + i);
					double bulge = YJKRGeometry.Geometry.GetBulge(xyz, xyz2, this.Center, true);
					WallInfos wallInfos = new WallInfos(xyz, xyz2, bulge, this.Thickness, id, this.WallId);
                    if (!YJKRGeometry.Geometry.LessThan(wallInfos.Length(), YJKArchMethodLibrary.Utils.Common.MMToFeet(10.0)))
					{
						list2.Add(wallInfos);
					}
				}
			}
			if (list2.Count > 1)
			{
				parts.AddRange(list2);
				return true;
			}
			return false;
		}

		public double Length()
		{
			if (this.IsArcWall)
			{
				XYZ center = this.Center;
				double num = this.m_Start.DistanceTo(center);
				double angle = YJKRGeometry.Geometry.getAngle(center, this.m_Start);
				double angle2 = YJKRGeometry.Geometry.getAngle(center, this.m_End);
				return YJKRGeometry.Geometry.BetweenTheAngles(angle, angle2, true) * num;
			}
			return this.m_Start.DistanceTo(this.m_End);
		}

		private XYZ m_Start;

		private XYZ m_End;

		private double m_Bugle;

		private double m_Thickness;

		private ElementId m_Id;

		private ElementId m_WallId;
	}
}
